﻿#################################
# BASIC Tenliners Contest 2020  #
#                               #
# Skydiver                      #
# (c) 2020 Roman Werner @romwer #
# email: roman.werner@gmail.com #
#################################

You carefully fold your parachute and look up to the blue sky. For five years now you have been trying for the perfect jump. You're a master in the accuracy landing discipline but never ever made it beyond the magic 30 points. And now Felix Baumgartner has booked you to learn precision jumping from the pro!

"Right! Today is the day! Let's go beyond the limits!" (...or die trying.)


Task and Goal
=============
In the Skydiver discipline "Accuracy Landing" you jump out of an aeroplane at 900-1100 meter (3000-3600 feet) and must hit a marked target on the ground called "dead center". The faster and closer you land to that target the more points you get. But don't open the parachute too early otherwise you lose valuable time points. Don't open the parachute too late (below 400m) or you will die!


Control:
========
Keyboard:
- To jump out of the aeorplane press any key.
- To open the parachute while falling press the <space> bar.
- To restart (after you touched ground) press any key.

Joystick:
Use <fire> in Joystick Port 1 for all actions.

Note: The skydiver itself cannot be controlled, so do a few trial jumps first to get a feel for the steady wind conditions.


Game Requirements:
==================
- C64/C128* with BASIC 2.0 runtime environment (or compatible)
- 1 Player

*Also playable on Windows/MacOS/iOS/Android (C64 Emulator required)


Starting in VICE: C64 emulator (http://vice-emu.sourceforge.net/):
==================================================================
Start the emulator and then drag and drop the "skydiver.prg" into the VICE window.
-or-
Load the program with the command: load "skydiver.prg",8
Then start the program with:       run


Skydiver BASIC program code:
============================
0v=53248:pokev+32,6:pokev+33,6:p=2040:z$="000000":m=400:c$="     {down}{left*5}":d$=c$+c$+c$
1d=829:pokev+39,3:t$="time:":k=198:p$=" {reverse on}{cm asterisk}{reverse off} {cm r}{cm r}{down}{left*5} {reverse on}C:{space*2}{reverse off}{cm w}{down}{left*6}{space*3}{cm y}Q{left*4}{up*3}"
2d=d+3:reada:c=0:fori=0to7:c=cor2^(7-i)and(aand2^i)>0:next:poked,a:poked+1,c:ifd<861goto2
3poked+64,a:poked+65,c:poke1882-d,a:poke1883-d,c:on-(d<892)goto2:h=1002:g=0:s=.5:pokep,14
4h$="{home}height:":pokev+21,0:print"{green}{clear}{yellow}";:fori=0to39:poke1984+i,160:next:o=rnd(0)*20:poke56275+o,1
5pokek,0:n=221:forj=0to1step0:fori=1to33:waitv+18,64:printp$;:geta$:ifa$=""thennext:printd$"{home}";:next
6printd$h$:printt$:x=40+i*8:pokev+21,1:ti$=z$:fory=54ton:geta$:ift=0andh<mtheng=-2:pokep,15:a$=""
7pokev,xand255:pokev+16,abs(x>=256):pokev+1,y:x=x+s:y=y-g:ifa$=" "andt=0thenpokep,13:g=s:t=y
8h=h-(6-6*g):print"{home}"tab(7)h"{left} ":printtab(8)ti$:next:print"{down}points:"t*(40-abs((x-4)/8-int(o+21)))/k
9waitk,1:t=0:goto3:data15,63,127,127,255,255,255,255,140,76,43,27,11,13,7,3,3,3,6,6,30


Skydiver BASIC program code (PUR-80 version using command abbreviations):
=========================================================================
0v=53248:pOv+32,6:pOv+33,6:p=2040:z$="000000":m=400:c$="     {down}{left*5}":d$=c$+c$+c$
1d=829:pOv+39,3:t$="time:":k=198:p$=" {reverse on}{cm asterisk}{reverse off} {cm r}{cm r}{down}{left*5} {reverse on}C:{space*2}{reverse off}{cm w}{down}{left*6}{space*3}{cm y}Q{left*4}{up*3}"
2d=d+3:rEa:c=0:fOi=0to7:c=cor2^(7-i)aN(aaN2^i)>0:nE:pOd,a:pOd+1,c:ifd<861gO2
3pOd+64,a:pOd+65,c:pO1882-d,a:pO1883-d,c:on-(d<892)gO2:h=1002:g=0:s=.5:pOp,14
4h$="{home}height:":pOv+21,0:?"{green}{clear}{yellow}";:fOi=0to39:pO1984+i,160:nE:o=rN(0)*20:pO56275+o,1
5pOk,0:n=221:fOj=0to1stE0:fOi=1to33:wAv+18,64:?p$;:gEa$:ifa$=""tHnE:?d$"{home}";:nE
6?d$h$:?t$:x=40+i*8:pOv+21,1:ti$=z$:fOy=54ton:gEa$:ift=0aNh<mtHg=-2:pOp,15:a$=""
7pOv,xaN255:pOv+16,aB(x>=256):pOv+1,y:x=x+s:y=y-g:ifa$=" "aNt=0tHpOp,13:g=s:t=y
8h=h-(6-6*g):?"{home}"tA7)h"{left} ":?tA8)ti$:nE:?"{down}points:"t*(40-aB((x-4)/8-int(o+21)))/k
9wAk,1:t=0:gO3:dA15,63,127,127,255,255,255,255,140,76,43,27,11,13,7,3,3,3,6,6,30

Tip: Copy/paste the program-Code into CBM prg Studio (http://www.ajordison.co.uk/).
There you can see the commands in nice color highlighting and you can directly execute the game in an emulator of your choice.


Skydiver Tenliner explained (000=row 0/100=row 1/...):
======================================================
000 v=53248: rem vic ii base address (used for skydiver sprite)
001 pokev+32,6: rem rem set border color to blue
002 pokev+33,6: rem rem set background color to blue
003 p=2040: rem 2040 = address of sprite data pointer for sprite 0
004 z$="000000": rem string to reset timer (ti$) with
005 m=400: rem meters before it is too late to pull the parachute
006 c$="     {down}{left*5}": rem empty line to print over airplane
007 d$=c$+c$+c$: rem 3x empty lines to cover the whole airplane

100 d=829: rem sprite 13 data (13x64=832) minus 3
101 pokev+39,3: rem set sprite 0 color to cyan
102 t$="time:": rem time label string
103 k=198: rem zeropage address of # keys waiting in keyboard buffer queue (>0 = key was pressed)
104 rem string of airplane gfx based on petscii:
105 p$=" {reverse on}{cm asterisk}{reverse off} {cm r}{cm r}{down}{left*5} {reverse on}C:{space*2}{reverse off}{cm w}{down}{left*6}{space*3}{cm y}Q{left*4}{up*3}"

200 d=d+3: rem skip to next line of sprite data
201 reada: rem read sprite data (left part/byte of skydiver)
202 c=0: rem clear mirror byte
203 fori=0to7: rem for 8 times...
204 c=cor2^(7-i)and(aand2^i)>0: rem mirror sprite data bits
205 next
206 poked,a: rem store left byte of skydiver
207 poked+1,c: rem store right (mirrored) byte of skydiver
208 ifd<861goto200: rem repeat as long as the top part of the parachute is reached 

300 poked+64,a: rem reuse this data in next sprite (man)
301 poked+65,c 
302 poke1882-d,a: rem reuse this data in next netxt sprite (man upside down)
303 poke1883-d,c
304 on-(d<892)goto200: rem continue until bottom sprite address has been reached
305 h=1002: rem height starting value
306 g=0: rem falling speed (gravity)
307 s=.5: rem horizontal speed of skydiver
308 pokep,14: rem set sprite 0 address pointer to address 896 (14x64=896)

400 h$="{home}height:": rem height label string
401 pokev+21,0: rem turn all sprites off
402 print"{green}{clear}{yellow}";: rem clear screen with green and set yellow as next print color
403 fori=0to39: rem for 40 characters...
404 poke1984+i,160: rem poke inverse space charcters to screen address (ground)
405 next
406 o=rnd(0)*20: rem find a random location for the landing spot and...
407 poke56275+o,1: rem ...turn that ground character to white (right half of screen)

500 pokek,0: rem clear keyboard buffer (to avoid unwanted previous key presses from buffer)
501 n=221: rem internal max value for position where skydiver touches ground
502 forj=0to1step0: rem infinite loop trick
503 fori=1to33: rem for 33 positions...
504 waitv+18,64: rem wait until 6th bit of rasterbeam is set (line is between 64 and 127)
505 printp$;: rem print plane
506 geta$: rem wait for key
507 ifa$=""thennext:printd$"{home}";:next: rem loop, then reset position of plane when at end of screen

600 printd$h$: rem print empty lines over plane
601 printt$: rem print time label
602 x=40+i*8: rem initial x position based on position where skydiver left plane
603 pokev+21,1: rem activate/show sprite 0
604 ti$=z$: rem reset timer to "000000"
605 fory=54ton: rem loop from plane position to where skydiver touches ground
606 geta$: rem wait for key
607 ift=0andh<mtheng=-2:pokep,15:a$="": rem when skydiver has not opened parachute before reaching 400m then: too late!
608 rem in that case set sprite 0 pointer to address of sprite 15 (15x64=960) = upside down man

700 pokev,xand255: rem set x position for sprite 0 (low byte)
701 pokev+16,abs(x>=256): rem set hi bit if x position is > 255 (or clear if not)
702 pokev+1,y: rem set y position for sprite 0
703 x=x+s: rem increase x position
704 y=y-g: rem makes y loop process faster or slower depending on g (-2 or +.5)
705 ifa$=" "andt=0thenpokep,13:g=s:t=y: rem when space bar is pressed while above 400m...
706 rem ... show man with parachute open, reduce falling speed and remember height for points

800 h=h-(6-6*g): rem calculate current height
801 print"{home}"tab(7)h"{left} ": rem show height status
802 printtab(8)ti$: rem show timer value
803 next
804 print"{down}points:"t*(40-abs((x-4)/8-int(o+21)))/k: rem when landed, show points

900 waitk,1: rem wait for key press
901 t=0: rem clear last height
902 goto300: rem restart game
903 data15,63,127,127,255,255,255,255,140,76,43,27,11,13,7,3,3,3,6,6,30
904 rem: above are the byte values for only the left half of the skydiver (calculating the other half was more economic)

2020 rem basic 10liners contest / (c) roman werner @romwer roman.werner@gmail.com


Trivia
======
This tenliner is somewhat special for me, because it is an adaption of the very first game I "kind of" owned or better: pirate copied.
The full (short) story about that game and my encounter with the C64 warehouse-scene in the early 80's you can find here (in German):
https://www.videospielgeschichten.de/mein-augenblick-des-glucks-in-videospielen-teil-4-8/#Roman-Werner

Following is a link to a YouTube video I found of a successful accuracy landing (don't watch if you have fear of heights):
https://www.youtube.com/watch?v=PDVeTj-zu-Q

